import { DrawerBase } from "./baseDrawers/DrawerBase"
import { Viewer, Entity } from "cesium"
import { PointDrawer } from "./baseDrawers/PointDrawer"
import { PolygonDrawer } from "./baseDrawers/PolygonDrawer"
import { PolylineDrawer } from "./baseDrawers/PolylineDrawer"
import { RectangleDrawer } from "./baseDrawers/RectangleDrawer"
import { ArrowDrawer } from "./baseDrawers/ArrowDrawer"
import { BezierDrawer } from "./baseDrawers/BezierDrawer"
import { SplineDrawer } from "./baseDrawers/SplineDrawer"
import { DrawerStyle } from "./style"
export type { DrawerStyle } from "./style"

/**
 * 绘制工具支持的图形类型枚举
 * @typedef {string} DrawerType
 * @values 'point', 'polyline', 'polygon', 'spline', 'bezier', 'rectangle', 'arrow'
 */
export type DrawerType =
  | "point" // 点
  | "polyline" // 折线
  | "polygon" // 多边形
  | "spline" // 样条曲线
  | "bezier" // 贝塞尔曲线
  | "rectangle" // 矩形
  | "arrow" // 箭头

/**
 * @description Cesium场景图形绘制工具类
 * 统一管理多种图形绘制器，支持动态切换绘制类型，提供完整的绘制生命周期控制
 *
 * @features
 * - 支持七种基本图形绘制：点、折线、多边形、矩形、样条曲线、贝塞尔曲线、箭头
 * - 统一的绘制控制接口：开始/结束绘制、清空、销毁等
 * - 自定义样式支持：通过DrawerStyle配置绘制外观
 * - 事件回调：提供图形闭合完成事件
 * - 快捷操作：支持【ctrl+z】撤销操作
 *
 * @example
 * // 1. 初始化绘制工具
 * const drawer = new Drawer(viewer, {
 *   point: { color: Cesium.Color.RED },
 *   polyline: { width: 3 }
 * });
 *
 * // 2. 设置绘制类型为多边形
 * drawer.type = 'polygon';
 *
 * // 3. 开始绘制
 * drawer.start();
 *
 * // 4. 监听图形闭合事件
 * drawer.onClose = (entity) => {
 *   console.log('多边形绘制完成', entity);
 * };
 *
 * // 5. 结束当前绘制
 * drawer.end();
 *
 * // 6. 清空所有绘制图形
 * drawer.clear();
 *
 * // 7. 销毁工具（组件卸载时调用）
 * drawer.destroy();
 */
export class Drawer {
  /**
   * 当前是否处于绘制状态
   * @type {boolean}
   * @default false
   */
  isDrawing: boolean = false

  /**
   * 当前激活的绘制器实例
   * @type {DrawerBase}
   * @protected
   */
  protected Instance: DrawerBase

  /**
   * 绘制器映射表，存储所有支持的图形绘制器
   * @type {Map<DrawerType, DrawerBase>}
   * @protected
   */
  protected drawerMap: Map<DrawerType, DrawerBase> = new Map()

  /**
   * 当前绘制类型的私有存储
   * @type {DrawerType}
   * @default 'point'
   * @protected
   */
  protected _type: DrawerType = "point"

  /**
   * 图形闭合事件的私有回调函数
   * @type {(e: Entity) => void}
   * @default 空函数
   * @protected
   */
  protected _onClose: (e: Entity) => void = () => {}

  /**
   * 获取当前绘制类型
   * @type {DrawerType}
   */
  get type() {
    return this._type
  }

  /**
   * 设置当前绘制类型（会自动切换绘制器）
   * @param {DrawerType} val - 目标绘制类型
   */
  set type(val: DrawerType) {
    if (val !== this.type) {
      this._type = val
      this.toggleDrawer() // 切换绘制器实例
    }
  }

  /**
   * 获取图形闭合事件回调
   * @type {(e: Entity) => void}
   */
  get onClose() {
    return this._onClose
  }

  /**
   * 设置图形闭合事件回调（会同步到所有绘制器）
   * @param {(e: Entity) => void} fn - 回调函数，参数为绘制完成的Entity
   */
  set onClose(fn: (e: Entity) => void) {
    this._onClose = fn
    // 同步回调到所有绘制器
    this.drawerMap.forEach((item) => {
      item.onClose = fn
    })
  }

  /**
   * 创建绘制工具实例
   * @constructor
   * @param {Viewer} viewer - Cesium Viewer实例
   * @param {DrawerStyle} [styleOption] - 全局绘制样式配置（可选）
   */
  constructor(
    public viewer: Viewer,
    public styleOption?: DrawerStyle,
  ) {
    this.initDrawerMap() // 初始化所有绘制器
    this.Instance = this.drawerMap.get(this.type) as PointDrawer
  }

  /**
   * 开始当前类型的图形绘制
   * @description 激活绘制状态，监听鼠标事件进行图形绘制
   * @returns {void}
   */
  start() {
    if (!this.isDrawing) {
      this.Instance.start()
      this.isDrawing = true
    }
  }

  /**
   * 结束当前图形绘制
   * @description 停止绘制状态，结束当前图形编辑
   * @returns {void}
   */
  end() {
    if (this.isDrawing) {
      this.Instance.end()
      this.isDrawing = false
    }
  }

  /**
   * 清空所有绘制的图形要素
   * @description 移除所有通过本工具绘制的Entity
   * @returns {void}
   */
  clear() {
    this.drawerMap.forEach((drawer) => {
      drawer.clear()
    })
  }

  /**
   * 销毁绘制工具
   * @description 彻底清理资源，移除所有事件监听和绘制的要素，释放内存
   * @returns {void}
   */
  destroy() {
    this.drawerMap.forEach((drawer) => {
      drawer.destroy()
    })
    // 清空映射表
    this.drawerMap.clear()
  }

  /**
   * 切换绘制器实例（内部使用）
   * @description 当绘制类型改变时，切换到对应绘制器并保持绘制状态
   * @protected
   * @returns {void}
   */
  protected toggleDrawer() {
    // 停止当前绘制器
    if (this.isDrawing) {
      this.Instance.end()
    }

    // 切换到新的绘制器
    this.Instance = this.drawerMap.get(this.type) as DrawerBase

    // 恢复绘制状态（如果之前处于绘制中）
    if (this.isDrawing) {
      this.Instance.start()
    }
  }

  /**
   * 初始化绘制器映射表（内部使用）
   * @description 创建所有支持的图形绘制器实例并存储到映射表
   * @protected
   * @returns {void}
   */
  protected initDrawerMap() {
    // 绘制器创建配置
    const drawerCreators: { [key in DrawerType]: DrawerBase } = {
      point: new PointDrawer(this.viewer, this.styleOption),
      polyline: new PolylineDrawer(this.viewer, this.styleOption),
      polygon: new PolygonDrawer(this.viewer, this.styleOption),
      spline: new SplineDrawer(this.viewer, this.styleOption),
      bezier: new BezierDrawer(this.viewer, this.styleOption),
      rectangle: new RectangleDrawer(this.viewer, this.styleOption),
      arrow: new ArrowDrawer(this.viewer, this.styleOption),
    }

    // 填充映射表
    for (const type in drawerCreators) {
      this.drawerMap.set(type as DrawerType, drawerCreators[type as DrawerType])
    }
  }
}
